package RMI;


import java.io.File;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.hibernate.*;
import org.hibernate.cfg.Configuration;



import Plugins.FileLabeler;
import Plugins.Loader;
import TagsDB.Plugin;
import TagsDB.PluginManager;
import TagsDB.TagedFile;
import TagsDB.TagedFilesManager;

/***
 * The managerAppGUI is class that support the application GUI
 * This class is Singleton
 * @author Guy
 *
 */
public class ManagerAppGUI implements Serializable
{
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private static ManagerAppGUI managerAppGUIinstance=new ManagerAppGUI();
	//members
	protected ArrayList<FileLabeler> listOfLabelers;
	protected Loader loader;
	protected ArrayList<String> optionsToSearch;
	File file = new File ("C:\\ourDropBox\\User\\hibernate.cfg.xml");
	SessionFactory sessionFactory=new Configuration().configure(file).buildSessionFactory();
	Session session=sessionFactory.openSession();


	//Methods
	/***
	 * get the used plugins
	 * @return ArrayList<FileLabeler>
	 */
	public ArrayList<FileLabeler> getListOfLabelers() {
		return listOfLabelers;
	}
	/**
	 * get instance of loader
	 * @return Loader
	 */
	public Loader getLoader() {
		return loader;
	}
	/**
	 * get instance of this class- Singleton
	 * @return ManagerGUI
	 */
	public static ManagerAppGUI getManagerAppGUIinstance() {
		return managerAppGUIinstance;
	}
	//Contractor of ManagerAppGUI
	private ManagerAppGUI() 
	{
		super();

		this.listOfLabelers = new ArrayList<FileLabeler>();
		this.loader=new Loader();
		this.optionsToSearch=new ArrayList<String>();


	}
	//TAGS
	/**
	 * add a tag to specific file
	 */
	public void addTagToFile(String strPathFile,String strfileName)
	{
		System.out.println("----MY PATH:"+strPathFile);
		//Connect to Database
		ArrayList<String> strings =null;
		listOfLabelers.clear();
		restorePlugin();//Take all the pluginss
		System.out.println("BEFORE ENTER TO LOAD AND SIZE IS:"+listOfLabelers.size());
		// for each used plugin make a tag
		for(int i=0; i<listOfLabelers.size(); i++)
		{
			strings=listOfLabelers.get(i).label(strPathFile);
			System.out.println("WOW");
			for(int j=0; j<strings.size(); j++)
			{
				System.out.println("AMAZING");
				System.out.println(strings.get(j).toString());
				//Create instance of tagedFile and set parameters
				TagedFile tagedFile=new TagedFile();
				tagedFile.setFilePath(strPathFile);
				tagedFile.setPluginDescription(strings.get(j).toString());
				tagedFile.setFileName(strfileName);
				TagedFilesManager manager = new TagedFilesManager(session);
				//Add to tagedFile table of tagsdatabase
				manager.saveTagedFile(tagedFile);
				session.flush();
			}
		}


	}
	/**
	 * remove tags from specific file
	 * @param strPathFile
	 */
	public void removeTagFromFile(String strPathFile)
	{
		//connect to DataBase
		//Get all the tags of the file
		String strQuery="FROM TagedFile t WHERE t.filePath=:filePathQry";
		Query query=session.createQuery(strQuery);
		query.setParameter("filePathQry", strPathFile);
		List<TagedFile> listPlugin=query.list();
		Iterator<TagedFile> itTagedFile=listPlugin.iterator();
		TagedFilesManager manager = new TagedFilesManager(session);

		while(itTagedFile.hasNext())
		{
			TagedFile tagedFile=itTagedFile.next();
			//delete tuple from table DB
			manager.deleteTagedFile(tagedFile);

			session.flush();
		}
	}
	//TAGS-search
	/**
	 * Search files according to file name and\or tags
	 */
	public ArrayList<TagedFile> search(String fileName,ArrayList<String> options)
	{
		ArrayList<TagedFile> resulArrayList=new ArrayList<TagedFile>();
		boolean first=true;
		boolean flagAddWhere=false;
		if(fileName.isEmpty() && options.isEmpty())
		{
			System.out.println("Stupid!");
			return null;
		}

		SessionFactory sessionFactory=new Configuration().configure().buildSessionFactory();
		Session session=sessionFactory.openSession();
		String strQuery="";
		Query query;

		//file name chose
		if(!fileName.isEmpty() && first)
		{
			flagAddWhere=true;
			first=false;
			strQuery+="FROM TagedFile t WHERE t.fileName LIKE "+"'%"+fileName.toString()+"%' ";			

		}

		for(int i=0; i<options.size(); i++)
		{

			if(flagAddWhere)
			{
				strQuery+="AND t.pluginDescription='"+options.get(i)+"' " ;
			}
			if(first)
			{
				flagAddWhere=true;
				first=false;
				strQuery+="FROM TagedFile t WHERE  t.pluginDescription='"+options.get(i).toString()+"' " ;		
			}

		}
		query=session.createQuery(strQuery);
		List<TagedFile> listTagedFile=query.list();
		Iterator<TagedFile> itTagedFile=listTagedFile.iterator();
		while(itTagedFile.hasNext())
		{

			TagedFile t=itTagedFile.next();
			System.out.println(t.getFilePath());
			resulArrayList.add(t);
		}

		return resulArrayList;

	}
	/**
	 * get array list of all tags to search
	 * @param check
	 * @param itemToSearch
	 * @return array list of option to search
	 */
	public ArrayList<String> optionsForSearch(boolean check,String itemToSearch)
	{
		if(check)
		{
			optionsToSearch.add(itemToSearch);
		}
		else
		{
			optionsToSearch.remove(itemToSearch);
		}
		return optionsToSearch;

	}
	/**
	 * get all options tags
	 * @return array list of strings
	 */
	public ArrayList<String> getOptionsToSearch() {
		return optionsToSearch;
	}
	/**
	 * clear options tags
	 */
	public void clearOptionsToSearch() {
		optionsToSearch.clear();
	}
	/**
	 * Get all the options of tags, for example Size plugin will return- {small,medium,large}
	 * @return array list of string
	 */
	public ArrayList<String> allOptionTags()
	{
		System.out.println("in all option tags method");
		ArrayList<String> options=new ArrayList<String>();
		
		ArrayList<Plugin> plugins=getPlugins();
		System.out.println("pLUGIN SIZE="+plugins.size());
		ArrayList<String> tempOptions=new ArrayList<String>();
		tempOptions.clear();
		for(Plugin p:plugins)
		{
			System.out.println("in options tag metode "+p.getIsUse());
			tempOptions=loader.loadFile(p.getPluginLocation()).allOption();
			for(int i=0; i<tempOptions.size(); i++)
			{
				System.out.println("I am stupid?"+ tempOptions.get(i).toString());
				System.out.println("found?"+tempOptions.indexOf(tempOptions.get(i)));
				if(options.indexOf(tempOptions.get(i))==-1)
				{
					System.out.println("adding?");
					options.add(tempOptions.get(i));
				}
			}
		}
		return options;

	}
	//PLUGIN-add plugins
	/**
	 * Get all the plugins that exist
	 */
	public ArrayList<Plugin> getPlugins()
	{
		Plugin plugin;
		String strQuery="FROM Plugin";
		Query query=session.createQuery(strQuery);
		List<Plugin> listPlugin=query.list();
		ArrayList<Plugin> arrlistPlugin=new ArrayList<Plugin>();

		Iterator<Plugin> itPlugin=listPlugin.iterator();
		System.out.println("AFTER MY SELECT");
		{
			//System.out.println(itPlugin.hasNext());
			boolean flag=itPlugin.hasNext();
			while(flag)
			{

				System.out.println("IN WHILE");
				plugin=itPlugin.next();

				/*int isUse=plugin.getIsUse();
				String strName=plugin.getNamePlugin();
				int id=plugin.getPluginID();
				String strPath=plugin.getPluginLocation();*/
				System.out.println(plugin.getNamePlugin());
				arrlistPlugin.add(plugin);

				flag=itPlugin.hasNext();
				/*System.out.println(itPlugin.hasNext());
				System.out.println(itPlugin.next().getPluginLocation());
				System.out.println(itPlugin.hasNext());*/

			}
		}
		return arrlistPlugin;

	}
	/**
	 * restore all the use plugins for the user
	 */
	public void restorePlugin()
	{
		System.out.println("I am restore data");
		String strQuery="FROM Plugin p WHERE p.isUse=:isUseQry";
		Query query=session.createQuery(strQuery);
		query.setParameter("isUseQry",1);
		List<Plugin> listPlugin=query.list();
		Iterator<Plugin> itPlugin=listPlugin.iterator();
		while(itPlugin.hasNext())
		{
			System.out.println("I am restore data1");
			Plugin plugin=itPlugin.next();
			listOfLabelers.add(loader.loadFile(plugin.getPluginLocation()));
		}

	}
	/**
	 * check if the plugin name is already exist
	 * @param pluginName
	 * @return true if the name plugin is new otherwise false
	 */
	public boolean checkPluginExist(String pluginName)
	{
		String strQuery="FROM Plugin p WHERE p.namePlugin=:pluginNameQry";
		Query query=session.createQuery(strQuery);
		query.setParameter("pluginNameQry", pluginName);
		List<Plugin> listPlugin=query.list();
		Iterator<Plugin> itPlugin=listPlugin.iterator();
		return (!(itPlugin.hasNext()));


	}
	/**
	 * change the status of the use plugin
	 * @param pluginName
	 * @param check
	 */
	public void updateUsePlugin(String pluginName,boolean check)
	{
		Plugin plugin;
		String strQuery="FROM Plugin p WHERE p.namePlugin=:pluginNameQry";
		Query query=session.createQuery(strQuery);
		query.setParameter("pluginNameQry", pluginName);
		List<Plugin> listPlugin=query.list();
		Iterator<Plugin> itPlugin=listPlugin.iterator();
		if(itPlugin.hasNext())
		{
			plugin=itPlugin.next();
			if(check)
			{

				plugin.setIsUse(1);
				listOfLabelers.add(loader.loadFile(plugin.getPluginLocation()));

			}
			else
			{
				System.out.println("REMOVE THE PLUGIN");
				plugin.setIsUse(0);
				listOfLabelers.remove(loader.loadFile(plugin.getPluginLocation()));
			}
			PluginManager manager = new PluginManager(session);

			manager.updatePlugin(plugin);

			session.flush();

		}


	}
	/**
	 * Add the tuple of plugin to dataBase in Plugins table
	 * @param strPath
	 * @param strNamePlugin
	 */
	public void addPluginToDB(String strPath,String strNamePlugin)
	{
		System.out.println("add the plugin");
		Plugin plugin = new Plugin();
		plugin.setNamePlugin(strNamePlugin);
		plugin.setPluginLocation(strPath);
		plugin.setIsUse(0);



		System.out.println("dsdsklds!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
		PluginManager manager = new PluginManager(session);

		manager.savePlugin(plugin);

		session.flush();


	}

}
